#!/usr/bin/env python2

import os
import sys
import errno
import getopt
import copy
import string

from color_output import red, yellow, blue, green, darkgreen
from utils import Exp, _dmsg, _dwarn, _derror, _exec_remote, _put_remote, _exec_pipe, _exec_pipe1,\
        _lock_file

tmp_path = "/tmp"
remote_path = "/opt/fusionstack"
local_path = os.path.dirname(os.path.abspath(__file__))

class Admin:
    def __init__(self):
        pass

    def get_hosts(self, path):
        hosts = []
        if not os.path.exists(path):
            raise Exp(errno.EINVAL, path + ' not found')
        with file(path, 'rb') as hosts_list:
            for line in hosts_list.readlines():
                if len(line.split()) != 1 and len(line.split()) != 2:
                    continue
                hosts.append(line.split()[0])

        return hosts

    def dispatch(self, host, user, password):
        cmd = remote_path + "/lich/libexec/lich.license -m sniffer"
        (out, err) = _exec_remote(host, cmd, user, password);
        if (out):
            fd = open(os.path.join(self.sniffer_path, host), 'w')
            fd.write(out)
            fd.close()
        if (err):
            raise Exp(errno.EPERM, err)

        cmd = remote_path + "/lich/libexec/lich.license -m list"
        (out, err) = _exec_remote(host, cmd, user, password);
        if (out):
            fd = open(os.path.join(self.liclist_path, host), 'w')
            fd.write(out)
            fd.close()
        if (err):
            raise Exp(errno.EPERM, err)

    def dispatchs(self, path, user, password, dispatch):
        fd = _lock_file("/var/run/license_dispatch.lock", 30, False)
        self.sniffer_path = os.path.join(tmp_path, "sniffer")
        if os.path.exists(self.sniffer_path):
            os.system("rm -rf %s/*" % self.sniffer_path)
        else:
            os.makedirs(self.sniffer_path)

        self.liclist_path = os.path.join(tmp_path, "liclist")
        if os.path.exists(self.liclist_path):
            os.system("rm -rf %s/*" % self.liclist_path)
        else:
            os.makedirs(self.liclist_path)

        self.dispatch_path = os.path.join(tmp_path, "dispatch")
        if os.path.exists(self.dispatch_path):
            os.system("rm -rf %s/*" % self.dispatch_path)
        else:
            os.makedirs(self.dispatch_path)

        hosts = self.get_hosts(path)
        for host in hosts:
            try:
                self.dispatch(host, user, password)
            except Exp, e:
                _derror("%s:%s" % (host, e.err))
            except IOError as err:
                _derror("%s:%s" % (host, str(err)))
            except Exception, e:
                _derror("%s:%s" % (host, str(e)))

        if dispatch:
            res = _exec_pipe([os.path.join(local_path, "license_dispatch"), "-i", os.path.join(local_path, "license"), "-d", path], 0, False)
            if 'effective' in res or 'distribution' in res or 'invalid time' in res:
                print res
                return

            for host in os.listdir(self.dispatch_path):
                _put_remote(host, os.path.join(self.dispatch_path, host), '/opt/fusionstack/license', user, password)

            print 'Dispatch success'
        else:
            res = _exec_pipe([os.path.join(local_path, "license_dispatch"), "-i", os.path.join(local_path, "license"), "-l", path], 0, False)
            print res,

        os.system("rm -rf %s/*" %(self.sniffer_path))
        os.system("rm -rf %s/*" %(self.liclist_path))
        os.system("rm -rf %s/*" %(self.dispatch_path))

    def sniffer(self):
        ump_ver = ''.zfill(40)
        try:
            Ump = __import__('Ump')
            ver_path =  os.path.join(os.path.dirname(Ump.__path__[0]), "git-info")
            with file(ver_path, 'rb') as ver:
                ump_ver = ver.readlines()[0].split()[1]
        except:pass

        res = _exec_pipe([os.path.join(local_path, "license_dispatch"), "-s"], 0, False)
        result = res.split()
        result[0] += ",ump_version:" + ump_ver
        print ' '.join(result)

    def recycle(self, confirm):
        api = __import__('Ump.objs.db.api', globals(), locals(), ['api'])
        hosts = api.host_get_all()
        hostips = [host.ip for host in hosts]

        if len(hostips) == 0:
            raise Exp(errno.EPERM, "No host found.")

        path = "/tmp/license_recycle_host_list.tmp"
        fd = open(path, 'w')
        for ip in hostips:
            fd.write(ip + "\n")
        fd.close()

        if confirm != 1:
            log = "/opt/fusionstack/log/license_recycle.log"
            print "host list:"
            os.system("echo 'host list:' >> " + log)
            path = "/tmp/license_recycle_host_list.tmp"
            for ip in hostips:
                print ip
                os.system("echo '%s' >> %s" %(ip, log))
            print ''

            (out, err) = _exec_pipe1([os.path.join(local_path, "license_dispatch"), "-i", os.path.join(local_path, "license"), "-r", path], 0, False)
            if (len(out) != 0):
                print out,
                os.system("echo '\n%s' >> %s" %(out.strip(), log))
        else:
            (out, err) = _exec_pipe1([os.path.join(local_path, "license_dispatch"), "-i", os.path.join(local_path, "license"), \
                                  "-r", path, "-c"], 0, False)

        os.system("rm -rf %s" %(path))

def usage():
    print ("usage:")
    print (sys.argv[0] + " --dispatch <hosts_path>")
    print (sys.argv[0] + " --list <hosts_path>")
    print (sys.argv[0] + " --recycle [--confirm]")
    print (sys.argv[0] + " --sniffer")
    print (sys.argv[0] + " -v")

def main():
    op = ""
    ext = None
    user = None
    password = None 
    confirm = 0;
    log = "/opt/fusionstack/log/license_recycle.log"

    try:
        opts, args = getopt.getopt(
            sys.argv[1:], 
            'hvu:p:', 
            ['user=', 'password=', 'help', 'dispatch=', 'list=', 'sniffer', 'recycle', 'confirm']
        )
    except getopt.GetoptError, err:
        print str(err)
        usage()
        exit(errno.EINVAL)

    newopts = copy.copy(opts)
    for o, a in opts:
        if o == '-v':
            (out, err) = _exec_pipe1([os.path.join(local_path, "license_dispatch"), "-v"], 0, False)
            if (len(out) != 0):
                print out,
            exit(0)
        if o in ('-u', '--user'):
            user = a
            newopts.remove((o, a))
        elif o in ('-p', '--password'):
            password = a
            newopts.remove((o, a))

    admin = Admin()

    for o, a in newopts:
        if o in ('--help'):
            usage()
            exit(0)
        elif o == '--dispatch':
            op = o
            ext = a
        elif o == '--list':
            op = o
            ext = a
        elif o == '--sniffer':
            op = o
        elif o == '--recycle':
            op = o
        elif o == '--confirm':
            confirm = 1;
        else:
            assert False, 'oops, unhandled option: %s, -h for help' % o
            exit(1)

    if (op == "--dispatch"):
        try:
            admin.dispatchs(ext, user, password, True)
        except Exp, e:
            _derror(e.err)
            exit(e.errno)
    elif (op == "--list"):
        try:
            admin.dispatchs(ext, user, password, False)
        except Exp, e:
            _derror(e.err)
            exit(e.errno)
    elif (op == "--sniffer"):
        try:
            admin.sniffer()
        except Exp, e:
            _derror(e.err)
            exit(e.errno)
    elif (op == "--recycle"):
        try:
            admin.recycle(confirm)
        except Exp, e:
            _derror(e.err)
            os.system("echo 'error:%s(%s)' >> %s" %(e.err.strip(), e.errno, log))
            exit(e.errno)

if __name__ == '__main__':
    if (len(sys.argv) == 1):
        usage()
    else:
        main()
